package com.change.websocket;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.time.Instant;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
@ServerEndpoint(value = "/ws/{key}")
public class WsServer {


    /**
     * 用来存放每个客户端对应的MyWebSocket对象。
     * key：WsServer
     */
    private static ConcurrentHashMap<String, WsServer> wsMap = new ConcurrentHashMap<>();

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;

    private String key;

    /**
     * 连接时执行
     */
    @OnOpen
    public void onOpen(@PathParam(value = "key") String key, Session session) {
        /*if (isExist(key)) {
            log.info("重复的<key:{}>连接，删除旧的key", key);
            del(key);
        }*/
        this.key = key + "_" + Instant.now().getEpochSecond();
        this.session = session;
        wsMap.put(this.key, this);
        log.info("有活跃连接ID:{} key:{} 当前连接数:{}", session.getId(), this.key, wsMap.size());
    }

    /**
     * 关闭时执行
     */
    @OnClose
    public void onClose(Session session) {
        log.info("ID:{} 关闭连接 key:{}", session.getId(), this.key);
        del(this.key);
    }

    /**
     * 收到消息时执行
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("ID:{} 收到消息:{}", session.getId(), message);
    }

    /**
     * 连接错误时执行
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.info("通道ID:{} 的连接错误:{}", session.getId(), error.getMessage());
    }

    /**
     * 消息广播
     */
    public static void broadcast(String message) {
        try {
            for (WsServer server : wsMap.values()) {
                server.session.getBasicRemote().sendText(message);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送消息
     */
    public static void sendMessage(String key, String message) {
        try {
            if (wsMap.containsKey(key)) {
                wsMap.get(key).send(message);
            }
        } catch (Exception e) {
            log.info("发送websocket消息异常：{}", e.getMessage());
        }
    }

    /**
     * 实现服务器主动推送
     */
    public void send(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接详情
     */
    public static Set linkInfo() {
        Set<Map.Entry<String, WsServer>> entries = wsMap.entrySet();
        return entries;
    }

    /**
     * 判断key是否存在
     */
    public static boolean isExist(String key) {
        boolean b = false;
        if (wsMap.containsKey(key)) {
            b = true;
        }
        return b;
    }

    /**
     * 删除连接
     */
    public static void del(String key) {
        try {
            WsServer wsServer = wsMap.get(key);
            wsServer.session.close();
            wsMap.remove(key);
        } catch (Exception e) {
            log.info("删除连接<key:{}>异常：{}", key, e);
        }
    }

    // 推送key枚举
    public enum WsEnum {
        DATA_BASE_INFO("data_base_info", "基础信息和监控数据key"),
        DATA_SINGLE_VOLTAGE("data_single_voltage", "单体电压key"),
        DATA_SINGLE_TEMP("data_single_temp", "单体温度key"),
        DATA_ALARM("data_alarm", "告警key");

        // 推送key
        private String key;
        // 说明
        private String explain;

        WsEnum(String key, String explain) {
            this.key = key;
            this.explain = explain;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getExplain() {
            return explain;
        }

        public void setExplain(String explain) {
            this.explain = explain;
        }
    }
}
